using System;

namespace InfiniTec.IO
{
	/// <summary>
	/// Summary description for ByteBag.
	/// </summary>
	internal class ByteBag : IEquatable<ByteBag>, IComparable<ByteBag>
	{
		readonly long _Size;
		readonly WeakReference _Reference;

		public long Size { get { return _Size; } }

		public byte[] GetBuffer()
		{
			return (byte[]) _Reference.Target;
		}

		public ByteBag(byte[] buffer)
		{
			_Size = buffer.Length;
			_Reference = new WeakReference(buffer, false);
		}

		/// <summary>
		/// Indicates whether the current object is equal to another object of the same type.
		/// </summary>
		/// <returns>
		/// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
		/// </returns>
		/// <param name="other">An object to compare with this object.
		///                 </param>
		public bool Equals(ByteBag other)
		{
			if (ReferenceEquals(null, other)) return false;
			if (ReferenceEquals(this, other)) return true;
			return other._Size == _Size;
		}

		/// <summary>
		/// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
		/// </summary>
		/// <returns>
		/// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
		/// </returns>
		/// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>. 
		///                 </param><exception cref="T:System.NullReferenceException">The <paramref name="obj"/> parameter is null.
		///                 </exception><filterpriority>2</filterpriority>
		public override bool Equals(object obj)
		{
			if (ReferenceEquals(null, obj)) return false;
			if (ReferenceEquals(this, obj)) return true;
			if (obj.GetType() != typeof (ByteBag)) return false;
			return Equals((ByteBag) obj);
		}

		/// <summary>
		/// Serves as a hash function for a particular type. 
		/// </summary>
		/// <returns>
		/// A hash code for the current <see cref="T:System.Object"/>.
		/// </returns>
		/// <filterpriority>2</filterpriority>
		public override int GetHashCode()
		{
			return _Size.GetHashCode();
		}

		public static bool operator ==(ByteBag left, ByteBag right)
		{
			return Equals(left, right);
		}

		public static bool operator !=(ByteBag left, ByteBag right)
		{
			return !Equals(left, right);
		}

		/// <summary>
		/// Compares the current object with another object of the same type.
		/// </summary>
		/// <returns>
		/// A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has the following meanings: 
		///                     Value 
		///                     Meaning 
		///                     Less than zero 
		///                     This object is less than the <paramref name="other"/> parameter.
		///                     Zero 
		///                     This object is equal to <paramref name="other"/>. 
		///                     Greater than zero 
		///                     This object is greater than <paramref name="other"/>. 
		/// </returns>
		/// <param name="other">An object to compare with this object.
		///                 </param>
		public int CompareTo(ByteBag other)
		{
			if (other == null) return 1;

			return Size.CompareTo(other.Size);
		}
	}
}